# coding=utf-8
from phosphorusScripts.bedcore.client import clientApi, compFactory, levelId, viewBinder, viewRequest
from phosphorusScripts.client.data import helper
from phosphorusScripts.common.shared import OptionType
from phosphorusScripts.modInfo import ModInfo


class MainScreen(clientApi.GetScreenNodeCls()):
    gameComp = compFactory.CreateGame(levelId)

    def __init__(self, namespace, uiName, param):
        super(MainScreen, self).__init__(namespace, uiName, param)
        self.client = clientApi.GetSystem(ModInfo.NAME, 'main')
        self.title = self.translate('phosphorus.main_screen.title')
        self.notSelected = self.translate('phosphorus.main_screen.not_selected')

    def Create(self):
        helper.selected = helper.selected

    def Destroy(self):
        helper.clear()

    # ===== 返回按钮 =====

    @viewBinder.binding(viewBinder.BF_InteractButtonClick, 'button.screen_exit')
    def handleScreenExitButton(self, args):
        self.SetRemove()
        return viewRequest.Refresh

    # ===== 标题内容 =====

    @viewBinder.binding(viewBinder.BF_BindString, '#title_text')
    def getTitleText(self):
        if helper.selected < 0:
            name = self.notSelected
        else:
            name = self.translate('phosphorus.{}.name'.format(helper.namespace))
        return self.title.format(name)

    # ===== 配置管理 =====

    @viewBinder.binding(viewBinder.BF_BindInt, '#config_count')
    def getConfigCount(self):
        return len(helper.configs)

    @viewBinder.binding(viewBinder.BF_ToggleChanged, 'toggle.config_selector')
    def handleConfigSelectorToggle(self, args):
        helper.selected = args['index']
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindBool, 'config_selectors', '#state')
    def getConfigSelectorsState(self, index):
        return index == helper.selected

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'config_selectors', '#text')
    def getConfigSelectorsText(self, index):
        if index >= len(helper.configs):
            return ''
        return self.translate('phosphorus.{}.name'.format(helper.configs[index]))

    # ===== 内容显示 =====

    @viewBinder.binding(viewBinder.BF_BindBool, '#content_visible')
    def getContentVisible(self):
        return helper.selected >= 0

    # ===== 配置信息 =====

    @viewBinder.binding(viewBinder.BF_BindString, '#config_display_name')
    def getConfigDisplayName(self):
        return '§l' + self.translate('phosphorus.{}.name'.format(helper.namespace))

    @viewBinder.binding(viewBinder.BF_BindString, '#config_authors')
    def getConfigAuthors(self):
        return self.translate('phosphorus.{}.authors'.format(helper.namespace))

    @viewBinder.binding(viewBinder.BF_BindString, '#config_description')
    def getConfigDescription(self):
        return self.translate('phosphorus.{}.description'.format(helper.namespace)).replace('\\n', '\n')

    # ===== 选项数量 =====

    @viewBinder.binding(viewBinder.BF_BindInt, '#option_count')
    def getOptionCount(self):
        return len(helper.options)

    # ===== 选项类型 =====

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#option_type')
    def getOptionCellsOptionType(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        return option['type']

    # ===== 选项是否可编辑 =====

    @viewBinder.binding_collection(viewBinder.BF_BindBool, 'option_cells', '#option.enabled')
    def getOptionCellsOptionEnabled(self, index):
        if index >= len(helper.options):
            return False
        option = helper.options[index]
        return helper.isop or not option['operator']

    # ===== 选项名称 =====

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#display_name')
    def getOptionCellsDisplayName(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        rawText = 'phosphorus.{}.{}.name'.format(helper.namespace, option['key'])
        displayName = self.translate(rawText)
        return '§l' + displayName

    # ===== 选项简介 =====

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#description')
    def getOptionCellsDescription(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        rawText = 'phosphorus.{}.{}.hint'.format(helper.namespace, option['key'])
        description = self.translate(rawText)
        if description == rawText:
            return ''
        return description.replace('\\n', '\n')

    # ===== 选项重置 =====

    @viewBinder.binding(viewBinder.BF_InteractButtonClick, 'button.option_reset')
    def handleOptionResetButton(self, args):
        index = args['#collection_index']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] == OptionType.BUTTON:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        option['current'] = option['default']
        self.sendOptionChanged(option)
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindBool, 'option_cells', '#option_reset.enabled')
    def getOptionCellsOptionResetEnabled(self, index):
        if index >= len(helper.options):
            return False
        option = helper.options[index]
        if option['type'] == OptionType.BUTTON:
            return False
        return option['current'] != option['default']

    # ===== 开关选项 =====

    @viewBinder.binding(viewBinder.BF_ToggleChanged, 'toggle.switch_option')
    def handleSwitchOptionToggle(self, args):
        index, state = args['index'], args['state']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] != OptionType.SWITCH:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        if state == option['current']:
            return viewRequest.Nothing
        option['current'] = state
        self.sendOptionChanged(option)
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindBool, 'option_cells', '#switch_option.current')
    def getOptionCellsSwitchOptionCurrent(self, index):
        if index >= len(helper.options):
            return False
        option = helper.options[index]
        if option['type'] != OptionType.SWITCH:
            return False
        return option['current']

    # ===== 枚举选项 =====

    @viewBinder.binding(viewBinder.BF_InteractButtonClick, 'button.enum_option')
    def handleEnumOptionButton(self, args):
        index = args['#collection_index']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] != OptionType.ENUM:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        def callback(value):
            if value == option['current']:
                return
            option['current'] = value
            self.sendOptionChanged(option)
        clientApi.PushScreen(ModInfo.NAME, 'enum', {
            'namespace': helper.namespace,
            'key': option['key'],
            'current': option['current'],
            'valid': option['valid'],
            'callback': callback,
        })
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#enum_option.current')
    def getOptionCellsEnumOptionCurrent(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        if option['type'] != OptionType.ENUM:
            return ''
        return self.translate('phosphorus.{}.{}.{}.name'.format(helper.namespace, option['key'], option['current']))

    # ===== 整型选项 =====

    @viewBinder.binding(viewBinder.BF_EditFinished, 'edit_box.int_option')
    def handleIntOptionEditBox(self, args):
        index, text = args['CollectionIndex'], args['Text']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] != OptionType.INT:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        if text == str(option['current']):
            return viewRequest.Nothing
        value = self.convertToInt(text, option['current'])
        option['current'] = max(min(value, option['max']), option['min'])
        self.sendOptionChanged(option)
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#int_option.current')
    def getOptionCellsIntOptionCurrent(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        if option['type'] != OptionType.INT:
            return ''
        return str(option['current'])

    # ===== 浮点型选项 =====

    @viewBinder.binding(viewBinder.BF_EditFinished, 'edit_box.float_option')
    def handleFloatOptionEditBox(self, args):
        index, text = args['CollectionIndex'], args['Text']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] != OptionType.FLOAT:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        if text == str(option['current']):
            return viewRequest.Nothing
        value = self.convertToFloat(text, option['current'])
        option['current'] = max(min(value, option['max']), option['min'])
        self.sendOptionChanged(option)
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#float_option.current')
    def getOptionCellsFloatOptionCurrent(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        if option['type'] != OptionType.FLOAT:
            return ''
        return str(option['current'])

    # ===== 颜色选项 =====

    @viewBinder.binding(viewBinder.BF_EditFinished, 'edit_box.color_option')
    def handleColorOptionEditBox(self, args):
        index, text = args['CollectionIndex'], args['Text']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] != OptionType.COLOR:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        if text == str(option['current']):
            return viewRequest.Nothing
        value = self.convertToColor(text, option['current'])
        option['current'] = value
        self.sendOptionChanged(option)
        return viewRequest.Refresh

    @viewBinder.binding_collection(viewBinder.BF_BindString, 'option_cells', '#color_option.current')
    def getOptionCellsColorOptionCurrent(self, index):
        if index >= len(helper.options):
            return ''
        option = helper.options[index]
        if option['type'] != OptionType.COLOR:
            return ''
        return option['current']

    @viewBinder.binding_collection(viewBinder.BF_BindColor, 'option_cells', '#color_option.color')
    def getOptionCellsColorOptionColor(self, index):
        if index >= len(helper.options):
            return 1.0, 1.0, 1.0, 1.0
        option = helper.options[index]
        if option['type'] != OptionType.COLOR:
            return 1.0, 1.0, 1.0, 1.0
        color = int(option['current'], 16)
        r = (color >> 16 & 255) * 0.00392156862745098
        g = (color >> 8 & 255) * 0.00392156862745098
        b = (color & 255) * 0.00392156862745098
        return r, g, b, 1.0

    # ===== 按钮选项 =====

    @viewBinder.binding(viewBinder.BF_InteractButtonClick, 'button.button_option')
    def handleButtonOptionButton(self, args):
        index = args['#collection_index']
        if index >= len(helper.options):
            return viewRequest.Nothing
        option = helper.options[index]
        if option['type'] != OptionType.BUTTON:
            return viewRequest.Nothing
        if not helper.isop and option['operator']:
            return viewRequest.Nothing
        self.sendOptionClicked(option)
        return viewRequest.Refresh

    def translate(self, rawText):
        """
        :type rawText: str
        :rtype: str
        """
        return str(self.gameComp.GetChinese(rawText))

    def convertToInt(self, text, default):
        """
        :type text: str
        :type default: int
        :rtype: int
        """
        try:
            return int(float(text))
        except StandardError:
            return default

    def convertToFloat(self, text, default):
        """
        :type text: str
        :type default: float
        :rtype: float
        """
        try:
            return float(text)
        except StandardError:
            return default

    def convertToColor(self, text, default):
        """
        :type text: str
        :type default: str
        :rtype: str
        """
        color = text.lstrip('#').lstrip('0x').lstrip('0X')
        try:
            return '{:0>6x}'.format(int(color, 16) & 0xffffff)
        except ValueError:
            return default

    def sendOptionChanged(self, option):
        """
        :type option: dict
        """
        eventData = {
            'namespace': helper.namespace,
            'key': option['key'],
            'value': option['current'],
        }
        if option['server']:
            self.client.NotifyToServer('OptionChangedEvent', eventData)
        else:
            self.client.BroadcastEvent('OptionChangedEvent', eventData)

    def sendOptionClicked(self, option):
        """
        :type option: dict
        """
        eventData = {
            'namespace': helper.namespace,
            'key': option['key'],
        }
        if option['server']:
            self.client.NotifyToServer('OptionClickedEvent', eventData)
        else:
            self.client.BroadcastEvent('OptionClickedEvent', eventData)
